import React, { useEffect, useState, Key } from 'react'
import {
  Form,
  Input,
  Button,
  Space,
  Card,
  Table,
  Tooltip,
  message,
  Modal,
} from 'antd'
import {
  SearchOutlined,
  EditOutlined,
  DeleteOutlined,
  ExclamationCircleOutlined,
} from '@ant-design/icons'

import { useNavigate } from 'react-router-dom'

import type { ColumnsType } from 'antd/es/table'

// 引入发送请求的函数
import {
  reqGetHospitalSet,
  reqDelOneHospitalSet,
  reqDelBatchHospitalSet,
} from '@api/hospitalSet'

// 引入ts类型
import {
  IhospitalSetList,
  IhospitalSetItem,
} from '@api/hospitalSet/model/hospitalSetTypes'

let flag = false // 这个变量用户判断当前用户是否点击查询。true点击了，false没点击
export default function HospitalSet() {
  // 将表格数据存储到状态中
  // 注意: 如果使用useState.初始值是空数组,则状态的类型自动推论为never[].解决办法: 告诉Ts,list是IhospitalSetList这个类型
  const [list, setList] = useState<IhospitalSetList>([])

  // 分页相关的状态
  const [total, setTotal] = useState(0) //数据总数
  const [pageSize, setPageSize] = useState(2) //一条几条
  const [page, setPage] = useState(1) //一条几条

  // 正在请求数据的loading状态值
  const [loading, setLoading] = useState(false)

  // 控制批量删除按钮的状态
  // const [disabled, setDisabled] = useState(true)
  // 存储用户选中的数据的id
  const [ids, setIds] = useState<Key[]>([])

  // 创建form实例
  const [form] = Form.useForm()

  // 获取navigate函数
  const navigate = useNavigate()

  // 注意: react中不建议把useEffect的挂载的回调定义成异步函数
  useEffect(() => {
    fetch(page, pageSize)
  }, [])
  // 获取医院设置表格数据的函数
  async function fetch(page: number, pageSize: number) {
    setLoading(true) //展示表格的loading效果
    // 直接从表单中获取医院名称和医院编码
    // 1. 创建一个form实例 const [form] = Form.useForm()
    // 2. 用form实例和Form组件进行绑定 在Form组件上写属性form={form实例}
    // 3. 对指定的Form组件进行操作(获取表单数据,设置表单数据)
    const { hosname, hoscode } = form.getFieldsValue()

    // 如果用户点击了查询按钮，则添加筛选条件。否则不添加
    let result
    if (flag) {
      result = await reqGetHospitalSet(page, pageSize, hosname, hoscode)
    } else {
      result = await reqGetHospitalSet(page, pageSize)
    }

    setList(result.records)
    setTotal(result.total)
    setLoading(false) // 隐藏表格的loading效果
  }

  // 表单点击提交按钮的事件处理函数
  const onFinish = (value: any) => {
    flag = true
    fetch(1, pageSize)
    setPage(1)
  }
  // 清空按钮的事件处理函数
  const clearForm = () => {
    // 1. 清空表单
    form.setFieldsValue({ hosname: undefined, hoscode: undefined })
    // 2. 重新获取表格数据
    flag = false
    fetch(1, pageSize)
    // 3. 从第一页开始
    setPage(1)
  }

  // 删除一条医院数据
  const delHospitalSet = (id: string) => {
    return async () => {
      // 发请求删除数据
      await reqDelOneHospitalSet(id)
      // 提示用户
      message.success('删除医院成功')
      // 重新获取表格数据
      fetch(page, pageSize)
    }
  }

  // 批量删除按钮的事件处理函数
  const clearAllSelect = () => {
    Modal.confirm({
      title: '您确定要删除这些数据吗?',
      icon: <ExclamationCircleOutlined />,
      // content: 'Some descriptions',
      // 确认按钮触发的事件处理函数
      async onOk() {
        await reqDelBatchHospitalSet(ids)
        setIds([]) //清空数组,让批量删除按钮禁用
        message.success('删除成功')
        fetch(page, pageSize)
      },
      // 取消按钮触发的事件处理函数
      // onCancel() {
      //   console.log('Cancel')
      // },
    })
  }

  // 注意: Table组件在基于Ts的环境下使用,要求在定义列数据的情况下,要通过泛型的形式,将未来表格渲染的数据对象的类型传入
  const columns: ColumnsType<IhospitalSetItem> = [
    // columns中的每一个对象控制了这一列展示什么内容
    {
      title: '序号', //决定了这个列的标题
      // dataIndex: 'age', //1. 当写了render函数之后,dataIndex的值决定了render函数的第一个参数是什么 2. 当不写render函数的之后,dataIndex就可以决定这一列渲染什么
      // key: 'name', // 数据中的键(id)
      render: (_, record, index) => {
        // render函数有三个参数:
        // _ 的值会变化,如果写dataIndex则有dataIndex决定,如果没有就是数据对象
        // record的值不会变化,就是数据对象
        // index的值不会变化,就是数据的下标
        return index + 1
      }, //render函数中返回什么则这一列就渲染什么
      align: 'center', //让这一列的内容水平居中
      width: 80, // 控制这一列的宽度
    },
    {
      title: '医院名称',
      dataIndex: 'hosname',
      // key: 'age',
    },
    {
      title: '医院编号',
      dataIndex: 'hoscode',
      // key: 'address',
    },
    {
      title: 'api基础路径',
      // key: 'tags',
      dataIndex: 'apiUrl',
    },
    {
      title: '签名',
      // key: 'tags',
      dataIndex: 'signKey',
    },
    {
      title: '联系人姓名',
      // key: 'tags',
      dataIndex: 'contactsName',
    },
    {
      title: '联系人手机号',
      // key: 'tags',
      dataIndex: 'contactsPhone',
    },
    {
      title: '操作',
      render: (_) => {
        return (
          <Space>
            {/* Tooltip的作用: 鼠标放到Button上面,则展示提示文本. title就是提示的内容 */}
            <Tooltip title="修改医院">
              <Button
                icon={<EditOutlined />}
                type="primary"
                onClick={() => {
                  navigate(`/syt/hospital/hospitalset/edit/${_.id}`)
                }}
              ></Button>
            </Tooltip>
            <Tooltip title="删除医院">
              <Button
                icon={<DeleteOutlined />}
                type="primary"
                danger
                onClick={delHospitalSet(_.id)}
              ></Button>
            </Tooltip>
          </Space>
        )
      },
      fixed: 'right', //让这一列固定在右侧
      width: 100,
    },
  ]
  return (
    // Card组件提供白色背景颜色,提供内边距
    <Card>
      {/* layout 用来控制表单中表单元素的排列方式. inline所有表单元素在一行显示 */}
      <Form
        layout="inline"
        onFinish={onFinish}
        form={form}
        onValuesChange={() => {
          //当用户表单中任何一个表单元素的值变化的时候触发
          // console.log(123)
          flag = false
        }}
      >
        {/* antd中每一个表单元素,要求被Form.Item包裹 */}
        <Form.Item name="hosname">
          <Input placeholder="医院名称"></Input>
        </Form.Item>
        <Form.Item name="hoscode">
          <Input placeholder="医院编码"></Input>
        </Form.Item>
        <Form.Item>
          {/* Space给组件之间添加间隔距离 */}
          <Space size={'small'}>
            {/* type="primary"就是主题颜色的按钮 */}
            {/* 给Button添加htmlType="submit"这个按钮才是表单的提交按钮 */}
            <Button type="primary" icon={<SearchOutlined />} htmlType="submit">
              查询
            </Button>
            <Button onClick={clearForm}>清空</Button>
          </Space>
        </Form.Item>
      </Form>

      <Space className="gap">
        <Button
          type="primary"
          onClick={() => {
            navigate('/syt/hospital/hospitalset/add')
          }}
        >
          添加
        </Button>
        <Button
          type="primary"
          danger
          disabled={!ids.length}
          onClick={clearAllSelect}
        >
          批量删除
        </Button>
      </Space>
      {/* columns: 代表表格中有多少列. 值应该是一个数组
        dataSource: 代表表格中有多少数据(行), 值也是数组
        bordered 给表格添加边框
         rowSelection 展示复选框
        scroll={{x:1500}} 控制是否展示滚动条. x表示水平方向滚动. 1500代表滚动区域是1500px
      */}
      <Table
        rowKey={'id'} // 当Table列表渲染数据时,告诉Table,使用每一条数据中的id作为列表渲染的key值
        columns={columns}
        dataSource={list}
        className="gap"
        bordered
        rowSelection={{
          // 只要点击了表格的复选框就会触发onchange
          onChange(selectedRowKeys: Key[], selectedRows: IhospitalSetItem[]) {
            // selectedRowKeys 是一个数组,里面存储了选中的数据的id
            // selectedRows 是一个数组,里面存储了选中的数据对象
            // console.log(selectedRowKeys)
            // setDisabled(!selectedRowKeys.length)
            setIds(selectedRowKeys)
          },
        }}
        scroll={{ x: 1500 }}
        loading={loading}
        // 这个属性用于控制Table内的分页器
        pagination={{
          current: page, //当前高亮的页码
          total, //table数据总数
          pageSize, //一页几条
          showSizeChanger: true, // 展示修改一页几条的下拉框
          pageSizeOptions: [2, 5, 10], //自定义渲染一页几条下拉框的选项
          showQuickJumper: true, //展示快速跳转到指定页,
          showTotal: (total) => {
            // return 什么,则分页器前面就展示什么
            return `总共${total}条`
          },
          onChange: (page, pageSize) => {
            // page 当前用户选择的页码
            // pageSize 当前用户选择的一页几条
            // console.log(page, pageSize)
            // 1. 动态的修改page和pageSize
            setPage(page)
            setPageSize(pageSize)
            // 2. 发送请求重新获取表格数据
            fetch(page, pageSize)
          },
        }}
      />
    </Card>
  )
}
